#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct note
{
	int u,v,w;
	note () {}
	note (int u,int v,int w) : u(u),v(v),w(w) {}
	bool operator<(const note &a)const
	{
		return w<a.w;
	}
}kp[1000010], p[200010];
int size[100010];
int n,m,  e;
long long ans;
int fa[100010];
int head[100010], ne[200010];
double epc, base;
void init(){
	e=0;
	epc=0;
	memset(head, -1, sizeof(head));
}
void addnote(int u, int v, int w){
	p[e]=note(u, v, w);
	ne[e]=head[u];
	head[u]=e++;
}
void dfs(int x, int f){
	size[x]=1;
	for(int i=head[x];i+1;i=ne[i])
		if (p[i].v !=f){
			dfs(p[i].v, x);
			size[x]+=size[p[i].v];
			epc=epc+(1LL*size[p[i].v]*(n-size[p[i].v]))*base*p[i].w;
		}
}
int find(int x)
{
	if (x==fa[x]) return x;
	fa[x]=find(fa[x]);
	return fa[x];
}
void Union(int a,int b)
{
	int A=find(a),B=find(b);
	fa[A]=B;
}
void kruskal()
{
	sort(kp,kp+m);
	int cnt=0;ans=0;
	for (int i=1;i<=n;i++) fa[i]=i;
	for (int i=0;i<m;i++) if (find(kp[i].u) != find(kp[i].v))
	{
		Union(kp[i].u,kp[i].v);
		addnote(kp[i].u, kp[i].v, kp[i].w);
		addnote(kp[i].v, kp[i].u, kp[i].w);
		ans+=kp[i].w;
		cnt++;
		if (cnt==n-1) break;
	}
}
int main(){
	int t;
	scanf("%d", &t);
	for (int TT=1;TT<=t;TT++){
		init();
		scanf("%d%d", &n, &m);
		base=1.0*n*(n-1)/2;
		base=1/base;
		for (int i=0;i<m;i++){
			scanf("%d%d%d",&kp[i].u, &kp[i].v, &kp[i].w);
		}
		kruskal();
		dfs(1, 1);
		printf("%I64d %.2f\n",ans, epc); 
	}
	return 0;
}
